package com.xiaomaoguai.fcp.pre.kepler.trace.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.api.HandlerContext;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.EmptyHeadHandler;
import com.xiaomaoguai.fcp.pre.kepler.router.router.RouterPipeline;
import com.xiaomaoguai.fcp.pre.kepler.trace.constants.KeplerTraceConstant;
import io.opentracing.Span;
import io.opentracing.tag.Tags;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Map;

/**
 * @author August.Zhang
 * @version v1.0.0
 * @date 2020/1/8 20:22
 * @since JDK 1.8
 */
public class HeadHandlerAroundInterceptor extends AbstractHandlerInterceptor {

	@Override
	public boolean accept(ProceedingJoinPoint pjp) {
		String typeName = pjp.getSignature().getDeclaringTypeName();
		Class<?> clazz = pjp.getSignature().getDeclaringType();
		return EmptyHeadHandler.class.isAssignableFrom(clazz) || StringUtils.equals(KeplerTraceConstant.STANDARD_HEAD_HANDLER_TYPE_NAME, typeName);
	}

	@Override
	public void invokeBeforeMethod(ProceedingJoinPoint pjp, Span span) {
		String handlerName = pjp.getSignature().getDeclaringType().getSimpleName();
		final Object[] args = pjp.getArgs();
		@SuppressWarnings("rawtypes") final RouterPipeline routerPipeline = (RouterPipeline) args[0];
		final Object innerParam = routerPipeline.getInnerParam();
		final String routerName = routerPipeline.getRouterName();
		final JSONObject beans = JSON.parseObject(JSON.toJSONString(routerPipeline.getRouterConfig())).getJSONObject("beans");
		final JSONObject routerConfig = beans.getJSONObject(routerName);
		String lockKey = null;
		if (routerConfig != null) {
			lockKey = routerConfig.getString(KeplerTraceConstant.SPAN_TAG_LOCK_KEY);
		}
		final String beforeJson = JSON.toJSONString(innerParam);
		final String productCode;
		if (innerParam instanceof JSONObject) {
			productCode = ((JSONObject) innerParam).getString(KeplerTraceConstant.SPAN_TAG_PRODUCT_CODE);
		} else {
			JSONObject jsonObject = JSON.parseObject(beforeJson);
			productCode = jsonObject.getString(KeplerTraceConstant.SPAN_TAG_PRODUCT_CODE);
		}

		Tags.COMPONENT.set(span, KeplerTraceConstant.TAG_COMPONENT_VALUE_HEAD);
		span.setTag(KeplerTraceConstant.SPAN_TAG_PRODUCT_CODE, productCode);
		span.setTag(KeplerTraceConstant.SPAN_TAG_ROUTER_NAME, routerName);
		span.setTag(KeplerTraceConstant.SPAN_TAG_HANDLER_NAME, handlerName);
		if (StringUtils.isNotBlank(lockKey)) {
			span.setTag(KeplerTraceConstant.SPAN_TAG_LOCK_KEY, lockKey);
		}
		span.setTag(KeplerTraceConstant.SPAN_TAG_BEFORE_ROUTER_IN, jaegerDataDesensitization.dataDesensitization(beforeJson));
	}

	@Override
	public void invokeAfterMethod(ProceedingJoinPoint pjp, Span span) {
		final Object[] returnArgs = pjp.getArgs();
		@SuppressWarnings("rawtypes") final HandlerContext handlerContext = (HandlerContext) returnArgs[0];
		final Map<String, Object> returnContext = handlerContext.getBuf().getContext();

		final String afterJson = JSON.toJSONString(returnContext);
		span.setTag(KeplerTraceConstant.SPAN_TAG_AFTER_ROUTER_IN, jaegerDataDesensitization.dataDesensitization(afterJson));
	}

}
